<?
namespace core;

/**
 * 
 */
class Http 
{
    private $option = [
        'url'=>'',
        'method'=>'GET',
        'data'=>[],
        'options'=>['timeout'=>20],
        'headers'=>[],
        'cookies'=>[],
    ];

    public $body = null;

    function __construct($opt=[])
    {
        $this->option = array_merge($this->option,$opt);
        return $this;
    }

    public function header($header=[])
    {
        $this->option['headers'] = array_merge($this->option['headers'],$header);
        return $this;
    }

    public function proxy($proxy)
    {
        $this->option['options'] = array_merge($this->option['options'],$proxy);
        return $this;
    }

    public function method($method='')
    {
        $this->option['method']=strtoupper($method);
        $this->curl();
        return $this;
    }

    public function location()
    {
        $this->option['method']='GET';
        $this->curl();
        return $this->header['location'][0]??null;
    }

    public function toJson()
    {
        try {
            return json_decode($this->body??'{}',true);
        } catch (\Throwable $e) {
            // loger($this->body);
        }
        
    }

    public static function url($url='')
    {
        $handler = new self(['url'=>$url]);
        return $handler;
    }

    private function curl() {
    $ch = curl_init($this->option['url']);
    if (empty($ch)) {
        throw new Exception('failed to curl_init');
    }
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($ch, CURLOPT_CUSTOMREQUEST, strtoupper($this->option['method']));
    $responseHeaders = $responseCookies = [];
    curl_setopt($ch, CURLOPT_HEADERFUNCTION, function ($ch, $header) use (&$responseHeaders, &$responseCookies) {
        $len    = strlen($header);
        $header = explode(':', $header, 2);
        if (count($header) < 2) {
            return $len;
        }
        $headerKey = strtolower(trim($header[0]));
        if ($headerKey == 'set-cookie') {
            [$k, $v]             = explode('=', $header[1]);
            $responseCookies[$k] = $v;
        } else {
            $responseHeaders[$headerKey][] = trim($header[1]);
        }
        return $len;
    });
    if ($this->option['data']) {
        curl_setopt($ch, CURLOPT_POSTFIELDS, $this->option['data']);
    }
    if ($this->option['headers']) {
        curl_setopt($ch, CURLOPT_HTTPHEADER, $this->option['headers']);
    }
    if ($this->option['cookies']) {
        $cookie_str = '';
        foreach ($this->option['cookies'] as $k => $v) {
            $cookie_str .= "{$k}={$v}; ";
        }
        curl_setopt($ch, CURLOPT_COOKIE, $cookie_str);
    }
    if (isset($this->option['options']['timeout'])) {
        if (is_float($this->option['options']['timeout'])) {
            curl_setopt($ch, CURLOPT_TIMEOUT_MS, intval($this->option['options']['timeout'] * 1000));
            curl_setopt($ch, CURLOPT_CONNECTTIMEOUT_MS, intval($this->option['options']['timeout'] * 1000));
        } else {
            curl_setopt($ch, CURLOPT_TIMEOUT, intval($this->option['options']['timeout']));
            curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, intval($this->option['options']['timeout']));
        }
    }
    if (isset($this->option['options']['connect_timeout'])) {
        if (is_float($this->option['options']['connect_timeout'])) {
            curl_setopt($ch, CURLOPT_CONNECTTIMEOUT_MS, intval($this->option['options']['connect_timeout'] * 1000));
        } else {
            curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, intval($this->option['options']['connect_timeout']));
        }
    }

    if (isset($this->option['options']['proxy'])) {
        curl_setopt($ch, CURLOPT_PROXY, $this->option['options']['proxy']);
    }

    if (isset($this->option['options']['auth'])) {
        curl_setopt($ch, CURLOPT_PROXYUSERPWD, $this->option['options']['auth']);
    }

    $this->body = curl_exec($ch);
    if ($this->body !== false) {
        $this->header = $responseHeaders;
        $this->cookie = $responseCookies;
        $this->status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
    } else {
        $this->err = 'HttpErr: No:'.curl_errno($ch).' Notice:'.curl_error($ch);
        // loger([curl_error($ch), curl_errno($ch)]);
        // loger('HttpErr: No:'.curl_errno($ch).' Notice:'.curl_error($ch));
    }
    
}

}